﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.Roster.FlattenedTroopRoster
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System;
using System.Collections;
using System.Collections.Generic;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.Roster
{
  public class FlattenedTroopRoster : IEnumerable<FlattenedTroopRosterElement>, IEnumerable
  {
    [SaveableField(1)]
    private readonly Dictionary<UniqueTroopDescriptor, FlattenedTroopRosterElement> _elementDictionary;

    internal static void AutoGeneratedStaticCollectObjectsFlattenedTroopRoster(
      object o,
      List<object> collectedObjects)
    {
      ((FlattenedTroopRoster) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      collectedObjects.Add((object) this._elementDictionary);
    }

    internal static object AutoGeneratedGetMemberValue_elementDictionary(object o)
    {
      return (object) ((FlattenedTroopRoster) o)._elementDictionary;
    }

    public FlattenedTroopRoster(int count = 4)
    {
      this._elementDictionary = new Dictionary<UniqueTroopDescriptor, FlattenedTroopRosterElement>(count);
    }

    public FlattenedTroopRoster(TroopRoster roster)
      : this(roster.Count)
    {
      this.Add(roster.GetTroopRoster());
    }

    public FlattenedTroopRoster(FlattenedTroopRoster other)
    {
      this._elementDictionary = new Dictionary<UniqueTroopDescriptor, FlattenedTroopRosterElement>((IDictionary<UniqueTroopDescriptor, FlattenedTroopRosterElement>) other._elementDictionary);
    }

    public FlattenedTroopRosterElement this[UniqueTroopDescriptor index]
    {
      get => this._elementDictionary[index];
      set => this._elementDictionary[index] = value;
    }

    public void Add(MBList<TroopRosterElement> roster)
    {
      foreach (TroopRosterElement troopRosterElement in (List<TroopRosterElement>) roster)
      {
        if (troopRosterElement.Number > 0)
        {
          int num1 = troopRosterElement.Xp / troopRosterElement.Number;
          int num2 = troopRosterElement.Xp % troopRosterElement.Number;
          for (int index = 0; index < troopRosterElement.Number; ++index)
          {
            bool isWounded = index < troopRosterElement.WoundedNumber;
            int xp = num1;
            if (index < num2)
              ++xp;
            this.Add(troopRosterElement.Character, isWounded, xp);
          }
        }
      }
    }

    public void Add(TroopRosterElement troop)
    {
      int num1 = troop.Xp / troop.Number;
      int num2 = troop.Xp % troop.Number;
      for (int index = 0; index < troop.Number; ++index)
      {
        bool isWounded = index < troop.WoundedNumber;
        int xp = num1;
        if (index < num2)
          ++xp;
        this.Add(troop.Character, isWounded, xp);
      }
    }

    public void Add(CharacterObject troop, int number, int woundedNumber = 0)
    {
      for (int index = 0; index < number; ++index)
      {
        this.Add(troop, woundedNumber > 0);
        --woundedNumber;
      }
    }

    public UniqueTroopDescriptor Add(CharacterObject troop, bool isWounded = false, int xp = 0)
    {
      FlattenedTroopRosterElement troopRosterElement = new FlattenedTroopRosterElement(troop, isWounded ? RosterTroopState.Wounded : RosterTroopState.Active, xp);
      this._elementDictionary.Add(troopRosterElement.Descriptor, troopRosterElement);
      return troopRosterElement.Descriptor;
    }

    public static int GenerateUniqueNoFromParty(MobileParty party, int troopIndex)
    {
      return (party.Party.Index * 999983 + troopIndex * 100003) % 616841;
    }

    public void Remove(UniqueTroopDescriptor descriptor)
    {
      this._elementDictionary.Remove(descriptor);
    }

    public IEnumerable<CharacterObject> Troops
    {
      get
      {
        foreach (FlattenedTroopRosterElement troopRosterElement in this._elementDictionary.Values)
          yield return troopRosterElement.Troop;
      }
    }

    public void Clear() => this._elementDictionary.Clear();

    public ICollection<FlattenedTroopRosterElement> RemoveIf(
      Predicate<FlattenedTroopRosterElement> match)
    {
      List<FlattenedTroopRosterElement> troopRosterElementList = new List<FlattenedTroopRosterElement>();
      foreach (KeyValuePair<UniqueTroopDescriptor, FlattenedTroopRosterElement> element in this._elementDictionary)
      {
        if (match(element.Value))
          troopRosterElementList.Add(element.Value);
      }
      foreach (FlattenedTroopRosterElement troopRosterElement in troopRosterElementList)
        this._elementDictionary.Remove(troopRosterElement.Descriptor);
      return (ICollection<FlattenedTroopRosterElement>) troopRosterElementList;
    }

    public UniqueTroopDescriptor FindIndexOfCharacter(CharacterObject character)
    {
      foreach (KeyValuePair<UniqueTroopDescriptor, FlattenedTroopRosterElement> element in this._elementDictionary)
      {
        if (element.Value.Troop == character)
          return element.Value.Descriptor;
      }
      return UniqueTroopDescriptor.Invalid;
    }

    public IEnumerator<FlattenedTroopRosterElement> GetEnumerator()
    {
      foreach (FlattenedTroopRosterElement troopRosterElement in this._elementDictionary.Values)
        yield return troopRosterElement;
    }

    IEnumerator IEnumerable.GetEnumerator() => (IEnumerator) this.GetEnumerator();

    public void OnTroopKilled(UniqueTroopDescriptor troopSeed)
    {
      FlattenedTroopRosterElement element = this._elementDictionary[troopSeed];
      this._elementDictionary[troopSeed] = new FlattenedTroopRosterElement(element.Troop, RosterTroopState.Killed, uniqueNo: element.Descriptor);
    }

    public void OnTroopWounded(UniqueTroopDescriptor troopSeed)
    {
      FlattenedTroopRosterElement element = this._elementDictionary[troopSeed];
      this._elementDictionary[troopSeed] = new FlattenedTroopRosterElement(element.Troop, RosterTroopState.WoundedInThisBattle, element.Xp, element.Descriptor, element.XpGained);
    }

    public void OnTroopRouted(UniqueTroopDescriptor troopSeed)
    {
      FlattenedTroopRosterElement element = this._elementDictionary[troopSeed];
      this._elementDictionary[troopSeed] = new FlattenedTroopRosterElement(element.Troop, RosterTroopState.Routed, element.Xp, element.Descriptor);
    }

    public int OnTroopGainXp(UniqueTroopDescriptor troopSeed, int xpAmount)
    {
      FlattenedTroopRosterElement element = this._elementDictionary[troopSeed];
      int xpGain = element.XpGained + xpAmount;
      int num = xpGain - element.XpGained;
      if (num == 0)
        return num;
      this._elementDictionary[troopSeed] = new FlattenedTroopRosterElement(element.Troop, element.State, element.Xp, element.Descriptor, xpGain);
      return num;
    }
  }
}
